﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;

namespace IPPoolModel
{
    public class IPPool
    {
        public IPPool()
        {
            _iPPortsList = new List<IPPorts>();
        }

        public IPPool Clone()
        {
            IPPool temp = new IPPool();
            temp.IPPortsList = new List<IPPorts>(_iPPortsList);
            temp.IpList = new List<IP>(IpList);
            return temp;
        }

        public List<IPPorts> IPPortsList
        {
            get
            {
                return _iPPortsList;
            }

            set
            {
                _iPPortsList = value;
            }
        }

        private List<IPPorts> _iPPortsList;
        [Newtonsoft.Json.JsonIgnore]
        public List<IP> IpList = new List<IP>();
        public bool AddIPAddressPool(IPPorts iPPorts)
        {
            if (iPPorts != null)
            {
                IPPorts ipPortsInside;
                //添加的IP地址是否存在
                if (IsContainIp(iPPorts, out ipPortsInside))
                {
                    List<int> portListTemp = PortsUnion(ipPortsInside.PortList, iPPorts.PortList);
                    myListForIP<PortRange> newPortRangeList = GetPortRangeList(portListTemp);
                    ipPortsInside.PortList = portListTemp;
                    ipPortsInside.PortRangeList.Clear();
                    ipPortsInside.PortRangeList.AddRange(newPortRangeList);
                }
                else
                {
                    _iPPortsList.Add(iPPorts);
                }
                return true;
            }
            else
                return false;
        }

        public void RemoveIPPorts(IPPorts iPPorts)
        {
            if (iPPorts != null)
            {
                bool ret = _iPPortsList.Remove(iPPorts);
            }
            GetIPAndPortList();
        }

        public void RemoveIPPool(IPPool iPPool, bool isUpdatePortRange = false)
        {
            if (iPPool != null)
            {
                if (!isUpdatePortRange)
                {
                    foreach (IPPorts ipPoolItem in iPPool.IPPortsList)
                    {
                        bool ret = _iPPortsList.Remove(ipPoolItem);
                    }
                }
                else
                {
                    foreach (IPPorts ipPoolItem in iPPool.IPPortsList)
                    {
                        IPPorts iPPorts = _iPPortsList.Find(x => x.Address == ipPoolItem.Address);
                        List<PortRange> prListTemp = new List<PortRange>(ipPoolItem.PortRangeList);
                        foreach (PortRange pr in prListTemp)
                        {
                            PortRange prTemp = iPPorts.PortRangeList.Find(x => x.Begin == pr.Begin && x.End == pr.End);
                            if (pr != null)
                                iPPorts.PortRangeList.Remove(prTemp);
                        }
                    }
                }
            }
            GetIPAndPortList();
        }
        /// <summary>
        /// 添加的IP地址是否存在
        /// </summary>
        /// <param name="ipPool">添加的IP端口段</param>
        /// <param name="ipPoolInside">地址池中相同IP</param>
        /// <returns></returns>
        private bool IsContainIp(IPPorts iPPorts, out IPPorts iPPortsInside)
        {
            iPPortsInside = _iPPortsList.Find(x => x.Address.Equals(iPPorts.Address));
            if (iPPortsInside != null)
                return true;
            else
                return false;
        }

        #region Contain IP

        /// <summary>
        /// 端口取并集
        /// </summary>
        /// <param name="OriPortList"></param>
        /// <param name="addPortList"></param>
        /// <returns></returns>
        private List<int> PortsUnion(List<int> OriPortList, List<int> addPortList)
        {
            IEnumerable<int> result = OriPortList.Union(addPortList);
            List<int> portListTemp = result.ToList();

            return portListTemp;
        }

        /// <summary>
        /// 提取端口为端口段 
        /// </summary>
        /// <param name="portList"></param>
        /// <returns></returns>
        private myListForIP<PortRange> GetPortRangeList(List<int> portList)
        {
            portList.Sort();
            myListForIP<PortRange> prList = new myListForIP<PortRange>();
            try
            {
                PortRange pr = new PortRange();
                List<int> portListTemp = new List<int>(portList);
                List<int> portListJudge = new List<int>();

                if (portListTemp.Count < 1)//如果为空返回空端口段集合
                    return prList;
                pr.Begin = portListTemp[0];
                pr.End = portListTemp[0];

                //遍历所有的端口号
                for (int i = 0; i < portListTemp.Count; i++)
                {
                    int Port = portListTemp[i];
                    portListJudge.Add(Port);//将端口号逐一加入需要判断的集合中
                    if (!IsContinue(portListJudge))//如果不是连续的
                    {
                        pr.End = portListJudge[i - 1];//结尾是上一个端口号
                        prList.Add(pr);


                        break;
                    }
                    else if (portListTemp.Count == 1)
                    {
                        prList.Add(pr);
                    }
                }
                if (portListJudge.Count > 2)
                    portListTemp.RemoveRange(0, portListJudge.Count - 1);
                else
                    portListTemp.RemoveRange(0, 1);

                if (portListTemp.Count > 0)
                {
                    List<PortRange> prListTemp = GetPortRangeList(portListTemp);
                    prList.AddRange(prListTemp);
                }
            }
            catch (Exception ex)
            {

            }

            return prList;
        }

        /// <summary>
        /// int集合是否连续
        /// </summary>
        /// <param name="portList"></param>
        /// <returns></returns>
        private bool IsContinue(List<int> portList)
        {
            if ((portList.Max() - portList.Min()) == portList.Count - 1)
                return true;
            else
                return false;
        }

        #endregion

        public void GetIPAndPortList()
        {
            IpList.Clear();
            foreach (IPPorts iPPorts in _iPPortsList)
            {
                iPPorts.PortList = iPPorts.GetPorts(iPPorts.PortRangeList);
                foreach (var item in iPPorts.PortList)
                {
                    IP ip = new IP
                    {
                        Address = iPPorts.Address,
                        Port = item
                    };
                    IpList.Add(ip);
                }

            }
        }

        public IP getRandomIP()
        {
            IP ip = IpList.OrderBy(u => Guid.NewGuid()).First();
            return ip;
        }

        public string getRandomIPstr()
        {
            IP ip = getRandomIP();
            string str = $"{ip.Address}:{ip.Port}";
            return str;
        }
    }

    public class IP
    {
        public string Address;
        public int Port;
    }

    /// <summary>
    /// 单IP+多个地址段
    /// </summary>
    public class IPPorts
    {
        public IPPorts()
        {
            Address = string.Empty;
            _portRangeList = new myListForIP<PortRange>();
            PortList = new List<int>();
            PortRangeList.CollectionChanged += PortRangeList_CollectionChanged;
        }

        public IPPorts(myListForIP<PortRange> portRangeList)
        {
            Address = string.Empty;
            PortRangeList = portRangeList;
            PortList = new List<int>();
            PortRangeList.CollectionChanged += PortRangeList_CollectionChanged;
        }
        private void PortRangeList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            PortList = GetPorts(_portRangeList);
        }

        public string Address { get; set; }

        public myListForIP<PortRange> PortRangeList
        {
            get { return _portRangeList; }
            set
            {
                _portRangeList = value;
            }
        }
        private myListForIP<PortRange> _portRangeList;

        [Newtonsoft.Json.JsonIgnore]
        public List<int> PortList { get; set; }

        /// <summary>
        /// 获取port段内所有的端口
        /// </summary>
        /// <param name="portRange"></param>
        /// <returns></returns>
        public List<int> GetPorts(List<PortRange> portRangeList)
        {
            List<int> portListTemp = new List<int>();
            foreach (PortRange portRange in portRangeList)
            {
                for (int port = portRange.Begin; port <= portRange.End; port++)
                {
                    if (!portListTemp.Contains(port))
                        portListTemp.Add(port);
                }
            }

            return portListTemp;
        }


    }

    public class myListForIP<T> : List<T>
    {
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (CollectionChanged != null)
            {
                CollectionChanged(this, e);
            }
        }

        public new void Add(T item)
        {
            base.Add(item);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
        }

        public new void AddRange(IEnumerable<T> collection)
        {
            base.AddRange(collection);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection));
        }

        public new void Clear()
        {
            base.Clear();
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public new void Insert(int index, T item)
        {
            base.Insert(index, item);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
        }

        public new void InsertRange(int index, IEnumerable<T> collection)
        {
            base.AddRange(collection);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection));
        }

        public new bool Remove(T item)
        {
            bool result = base.Remove(item);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
            return result;
        }

        public new int RemoveAll(Predicate<T> match)
        {
            List<T> item = FindAll(match);
            int result = base.RemoveAll(match);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
            return result;
        }

        public new void RemoveAt(int index)
        {
            List<T> item = GetRange(index, 1);
            base.RemoveAt(index);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
        }

        public new void RemoveRange(int index, int count)
        {
            List<T> item = GetRange(index, count);
            base.RemoveRange(index, count);
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
        }

    }
    public class PortRange
    {
        public PortRange()
        {

        }
        public PortRange(int beginNo, int endNo)
        {
            Begin = beginNo;
            End = endNo;
        }

        public PortRange(string beginNo, string endNo)
        {
            int begin = 0, end = 0;
            bool ret1 = int.TryParse(beginNo, out begin);
            bool ret2 = int.TryParse(endNo, out end);
            if (ret1 && ret2)
            {
                Begin = begin;
                End = end;
            }
        }
        public int Begin { get; set; }
        public int End { get; set; }
    }
}
